package com.yupi.yoj.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yupi.yoj.common.ErrorCode;
import com.yupi.yoj.constant.RedisConstant;
import com.yupi.yoj.exception.BusinessException;
import com.yupi.yoj.exception.ThrowUtils;
import com.yupi.yoj.mapper.QuestionSubmitMapper;
import com.yupi.yoj.model.dto.questionsubmit.QuestionSubmitQueryRequest;
import com.yupi.yoj.model.dto.questionsubmit.QuestionSubmitVO;
import com.yupi.yoj.model.entity.Question;
import com.yupi.yoj.model.entity.QuestionSubmit;
import com.yupi.yoj.model.entity.User;
import com.yupi.yoj.model.vo.UserVO;
import com.yupi.yoj.service.QuestionService;
import com.yupi.yoj.service.QuestionSubmitService;
import com.yupi.yoj.service.UserService;
import io.jsonwebtoken.lang.Collections;
import io.swagger.annotations.Scope;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
* @author 46411
* @description 针对表【question_submit(题目提交)】的数据库操作Service实现
* @createDate 2024-09-23 23:37:52
*/
@Service
@Transactional
public class QuestionSubmitServiceImpl extends ServiceImpl<QuestionSubmitMapper, QuestionSubmit>
    implements QuestionSubmitService{

    @Autowired
    UserService userService;

//    @Autowired
    QuestionService questionService;

    @Autowired
    public QuestionSubmitServiceImpl(QuestionService questionService) {
        this.questionService = questionService;
    }

    @Autowired
    RedissonClient redissonClient;

    @Override
    public Long addQuestionSubmit(QuestionSubmit questionSubmit) {
        if (questionSubmit == null) throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        Boolean res = this.save(questionSubmit);
        ThrowUtils.throwIf(!res, ErrorCode.SYSTEM_ERROR, "提交失败");
        return questionSubmit.getId();
    }

    @Override
    public void updateQuestionSubmitById(QuestionSubmit questionSubmit) {
        if (questionSubmit == null || questionSubmit.getId() <= 0) throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        Boolean res = this.updateById(questionSubmit);
        ThrowUtils.throwIf(!res, ErrorCode.NOT_FOUND_ERROR, "未找到对应提交");
    }

    @Override
    public void deleteQuestionSubmitById(Long id) {
        if (id == null || id <= 0) throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        boolean res = this.removeById(id);
        ThrowUtils.throwIf(!res, ErrorCode.NOT_FOUND_ERROR, "删除失败");
    }

    @Override
    public List<QuestionSubmitVO> getQuestionSubmitByUId(Long uid) {
        QueryWrapper<QuestionSubmit> qdwp = new QueryWrapper<>();
        qdwp.eq("userid", uid);
        List<QuestionSubmit> submits = this.list(qdwp);
        if (submits == null || submits.size() == 0) throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "未找到对应提交");

        return getQuestionSubmitVO(submits);
    }

    @Override
    public List<QuestionSubmitVO> getQuestionSubmitByUIdQId(Long uid, Long qid) {
        QueryWrapper<QuestionSubmit> qdwp = new QueryWrapper<>();
        qdwp.eq("userId", uid);
        qdwp.eq("questionId", qid);
        List<QuestionSubmit> submitList = this.list(qdwp);
        ThrowUtils.throwIf (submitList == null, ErrorCode.NOT_FOUND_ERROR, "未找到对应提交");
        return this.getQuestionSubmitVO(submitList);
    }
    public QuestionSubmitVO getQuestionSubmitVO(QuestionSubmit questionSubmit) {
        QuestionSubmitVO questionSubmitVO = new QuestionSubmitVO();
        BeanUtils.copyProperties(questionSubmit, questionSubmitVO);
        // 根据uid查用户
        User user = userService.getById(questionSubmit.getUserid());
        ThrowUtils.throwIf(user == null, ErrorCode.NOT_FOUND_ERROR, "用户不存在");
        UserVO userVO = userService.getUserVO(user);
        questionSubmitVO.setUserVO(userVO);
        // 根据题目id查题目
        Question question = questionService.getById(questionSubmit.getQuestionid());
        ThrowUtils.throwIf(question == null, ErrorCode.NOT_FOUND_ERROR, "用户不存在");
        questionService.getQuestionVO(question);
        return questionSubmitVO;
    }


    @Override
    public List<QuestionSubmitVO> getQuestionSubmitVO(List<QuestionSubmit> questionSubmitList) {
        LinkedList<QuestionSubmitVO> questionSubmitVOS = new LinkedList<>();
        for (int i = 0; i < questionSubmitList.size(); i++) {
            QuestionSubmitVO questionSubmitVO = new QuestionSubmitVO();
            BeanUtils.copyProperties(questionSubmitList.get(i), questionSubmitVO);
            questionSubmitVOS.add(questionSubmitVO);
        }
        return questionSubmitVOS;
    }

    @Override
    public Wrapper<QuestionSubmit> getQueryWrapper(QuestionSubmitQueryRequest questionSubmitQueryRequest) {
        QueryWrapper<QuestionSubmit> qwp = new QueryWrapper<>();
        return qwp;
    }

    @Override
    public String readFile(MultipartFile file) {
        ThrowUtils.throwIf(file == null, ErrorCode.PARAMS_ERROR, "文件为空");
        String fileContent = "";
        try {
            // 获取文件名
            String fileName = file.getOriginalFilename();
            String localPathPrefix = getDefualtFileDir();
            //获取文件后缀
            String fileLastFix = fileName.substring(fileName.lastIndexOf("."));
            ThrowUtils.throwIf(!fileLastFix.equals(".txt"), ErrorCode.PARAMS_ERROR, "文件格式错误(只能上传txt文件)");

            String localPath = localPathPrefix + "\\" + fileName;
            File localFile = new File(localPath);
            if (!localFile.getParentFile().exists()) {
                localFile.getParentFile().mkdirs();
            }
            //写入到本地磁盘
            file.transferTo(localFile);
            // 获取文件在本地磁盘上的路径
            String filePath = localFile.getAbsolutePath();
            System.out.println("文件名称: 已经存入本地磁盘，全路径为："+filePath);
            //成功 读取文件 返回内容
            fileContent = getTXTFileContent(filePath);
            deleteFileDir( localFile, localPathPrefix);
        }catch (Exception e){
            e.printStackTrace();
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, e.getMessage());
        }
        return fileContent;
    }

    @Override
    public QuestionSubmitVO getQuestionSubmitVOById(Long id) {
        QuestionSubmit questionSubmit = getById(id);
        ThrowUtils.throwIf(questionSubmit == null, ErrorCode.NOT_FOUND_ERROR, "未找到对应提交记录");
        return getQuestionSubmitVO(questionSubmit);
    }

    /**
     * 向redis中添加提交记录
     * @param userid
     */
    @Override
    public void addQuestionSubmitTimes(Long userid) {
        LocalDate date = LocalDate.now();
        String key = RedisConstant.getUserYearSubmitTimesMapRedisKey(date.getYear(), userid);
        RMap<Integer, Integer> yearSubmitTimesMap = redissonClient.getMap(key);
//        if (yearSubmitTimesMap == null) yearSubmitTimesMap = new ;
        // 今年还剩天数
        int restDay = date.lengthOfYear() - date.getDayOfYear() + 1;
        // 设置过期时间
        yearSubmitTimesMap.expire(restDay, TimeUnit.DAYS);

        // 获取当前日期是一年中的第几天，作为偏移量（从 1 开始计数）
        int offset = date.getDayOfYear();
        // 检查当天是否已经签到
        if (yearSubmitTimesMap.containsKey(offset)) {
            int times = (int)yearSubmitTimesMap.get(offset);
            ThrowUtils.throwIf (times >RedisConstant.MAX_SUBMIT_TIMES_PER_DAY, ErrorCode.FORBIDDEN_ERROR, "每天能提交的次数已经达到上限");
            yearSubmitTimesMap.put(offset,  times + 1);
        }else {
            yearSubmitTimesMap.put(offset,1);
        }
    }



    private String getDefualtFileDir() throws FileNotFoundException {
        String localPath = "";
        //1.1获取当前日期,当做本地磁盘的目录
        Date nowDate = new Date(System.currentTimeMillis());
        String format = new SimpleDateFormat("YYYYMMDD").format(nowDate);
        String localPathPrefix = ResourceUtils.getFile("classpath:").getAbsolutePath() + format;

        // 保存文件到本地磁盘
        localPath = localPathPrefix;
        return localPath;
    }

    private String getTXTFileContent(String filePath) {
        StringBuffer sb = new StringBuffer();
        try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    /**
     * 删除文件、文件夹
     * @return
     */
    private Boolean deleteFileDir(File localFile, String localPathPrefix) {
        //删除本地临时磁盘文件
        if (localFile.delete()) {
            System.out.println(localFile.getName() + "已经删除");
        } else {
            System.out.println("文件删除失败");
        }
        //删除本次磁盘的日期目录
        File file1 = new File(localPathPrefix);
        if (file1.delete()) {
            System.out.println(file1.getName() + "已经删除");
        } else {
            System.out.println("文件删除失败");
        }
        return true;
    }

    /**
     * 获取这一年的提交次数
     */
    @Override
    public RMap<Integer, Integer> getSubmitCountByYear(Long userid) {
        LocalDate date = LocalDate.now();
        int year = date.getYear();
        String userYearSubmitTimesMapRedisKey = RedisConstant.getUserYearSubmitTimesMapRedisKey(year, userid);
        RMap<Integer, Integer> userSubmitTimesMap = redissonClient.getMap(userYearSubmitTimesMapRedisKey);
       /* userSubmitTimesMap.entrySet().stream()
        .sorted(Map.Entry.comparingByKey()) // 使用自然顺序排序Key
        .map(Map.Entry::getValue)           // 提取每个Entry的Value
        .collect(Collectors.toList());      // 收集整理成List*/
        return userSubmitTimesMap;
    }

    @Override
    public List<QuestionSubmit> getQuestionSubmitByIds(Long[] subids) {
        ThrowUtils.throwIf(subids == null, ErrorCode.PARAMS_ERROR, "参数错误");
        QueryWrapper<QuestionSubmit> questionSubmitQueryWrapper = new QueryWrapper<>();
        questionSubmitQueryWrapper.in("id", subids);
        List<QuestionSubmit> submits = this.list(questionSubmitQueryWrapper);
        ThrowUtils.throwIf(Collections.isEmpty(submits), ErrorCode.NOT_FOUND_ERROR, "题目不存在");
        return submits;
    }

}




